package com.lace.security.jwt.util;

import com.lace.security.jwt.SecurityProperties;
import com.lace.security.jwt.auth.UserContext;
import com.lace.security.jwt.exception.ExpiredTokenException;
import io.jsonwebtoken.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * Created by WangZX on 2018/7/14.
 */
@Component
public class JwtTokenUtil {
	
	private static final Logger logger = LoggerFactory.getLogger(JwtTokenUtil.class);

	@Autowired
	private SecurityProperties settings;


	public String createAccessToken(UserContext userContext) {
		Claims claims = Jwts.claims().setSubject(userContext.getUserName());
		List<String> authorities = new ArrayList<>();
		for (GrantedAuthority authority : userContext.getAuthorities()) {
			authorities.add(authority.toString());
		}
		claims.put("roles", authorities);

		String token = Jwts.builder().
				setClaims(claims).
				setIssuedAt(new Date()).
				setExpiration(new Date(System.currentTimeMillis() + settings.getTokenExpirationTime() * 1000)).
				signWith(SignatureAlgorithm.HS512, settings.getTokenSigningKey()).
				compact();

		return token;
	}

	public String createRefreshToken(UserContext userContext) {

		Claims claims = Jwts.claims().setSubject(userContext.getUserName());
		claims.put("roles", Arrays.asList("TOKEN"));

		String token = Jwts.builder().
				setClaims(claims).
				setIssuedAt(new Date()).
				setId(UUID.randomUUID().toString()).
				setExpiration(new Date(System.currentTimeMillis() + settings.getRefreshTokenExpTime() * 1000)).
				signWith(SignatureAlgorithm.HS512, settings.getTokenSigningKey()).
				compact();

		return token;
	}
	
	public Jws<Claims> parseClaims(String token) {
        try {
            return Jwts.parser().setSigningKey(settings.getTokenSigningKey()).parseClaimsJws(token);
        } catch (UnsupportedJwtException | MalformedJwtException | IllegalArgumentException | SignatureException ex) {
            logger.warn("token校验错误");
            throw new BadCredentialsException("认证失败！令牌校验错误", ex);
        } catch (ExpiredJwtException expiredEx) {
            logger.warn("token过期");
            throw new ExpiredTokenException(token, "认证令牌过期，请重新登录", expiredEx);
        }
    }
}
